<?php

declare(strict_types=1);
/**
 * Copyright (c) The Magic , Distributed under the software license
 */

namespace Dtyq\CloudFile\Tests\FileService;

use Dtyq\CloudFile\Kernel\FilesystemProxy;
use Dtyq\CloudFile\Kernel\Struct\AppendUploadFile;
use Dtyq\CloudFile\Kernel\Struct\CredentialPolicy;
use Dtyq\CloudFile\Kernel\Struct\UploadFile;
use Dtyq\CloudFile\Tests\CloudFileBaseTest;
use Exception;

/**
 * @internal
 * @coversNothing
 */
class FileServiceTest extends CloudFileBaseTest
{
    public function testGetUploadTemporaryCredential()
    {
        $filesystem = $this->getFilesystem();

        $credentialPolicy = new CredentialPolicy([
            'sts' => false,
            'roleSessionName' => 'test',
        ]);
        $res = $filesystem->getUploadTemporaryCredential($credentialPolicy, $this->getOptions($filesystem->getOptions()));
        $this->assertArrayHasKey('signature', $res['temporary_credential']);
        $this->assertArrayHasKey('expires', $res['temporary_credential']);

        $credentialPolicy = new CredentialPolicy([
            'sts' => true,
            'roleSessionName' => 'test',
        ]);
        $res = $filesystem->getUploadTemporaryCredential($credentialPolicy, $this->getOptions($filesystem->getOptions()));
        $this->assertArrayHasKey('sts_token', $res['temporary_credential']);
        $this->assertArrayHasKey('expires', $res['temporary_credential']);
    }

    public function testGetPreSignedUrls()
    {
        $filesystem = $this->getFilesystem($this->getStorageName());

        $list = $filesystem->getPreSignedUrls([
            'easy-file/file-service.txt',
            'easy-file/test.txt',
        ], 3600, $this->getOptions($filesystem->getOptions()));

        $this->assertEmpty($list);
    }

    public function testSimpleUpload()
    {
        $filesystem = $this->getFilesystem();

        $credentialPolicy = new CredentialPolicy([
            'sts' => false,
        ]);

        $realPath = __DIR__ . '/../test.txt';

        $uploadFile = new UploadFile($realPath, 'easy-file');
        $filesystem->uploadByCredential($uploadFile, $credentialPolicy, $this->getOptions($filesystem->getOptions()));
        $this->assertTrue(true);
    }

    public function testSimpleUploadByUrl()
    {
        $filesystem = $this->getFilesystem();

        $list = $filesystem->getLinks([
            'easy-file/file-service.txt',
        ], [], 3600, $this->getOptions($filesystem->getOptions()));
        $this->assertArrayHasKey('easy-file/file-service.txt', $list);
        $link = $list['easy-file/file-service.txt']->getUrl();

        $credentialPolicy = new CredentialPolicy();

        $uploadFile = new UploadFile($link, 'easy-file');
        $filesystem->uploadByCredential($uploadFile, $credentialPolicy, $this->getOptions($filesystem->getOptions()));
        $this->assertTrue(true);
    }

    public function testSimpleUploadByBase64()
    {
        $filesystem = $this->getFilesystem($this->getStorageName());
        $credentialPolicy = new CredentialPolicy();

        $uploadFile = new UploadFile('', 'easy-file');
        $filesystem->uploadByCredential($uploadFile, $credentialPolicy, $this->getOptions($filesystem->getOptions()));
        $this->assertTrue(true);

        $list = $filesystem->getLinks([
            $uploadFile->getKey(),
        ], [], 7200, $this->getOptions($filesystem->getOptions()));
        var_dump(current($list)->getUrl());
    }

    public function testGetMetas()
    {
        $filesystem = $this->getFilesystem();

        $list = $filesystem->getMetas([
            'easy-file/file-service.txt',
            'easy-file/test.txt',
        ], $this->getOptions($filesystem->getOptions()));
        $this->assertArrayHasKey('easy-file/file-service.txt', $list);
        $this->assertArrayHasKey('easy-file/test.txt', $list);
    }

    public function testGetLinks()
    {
        $filesystem = $this->getFilesystem();

        $list = $filesystem->getLinks([
            'easy-file/file-service.txt',
            'easy-file/test.txt',
        ], [], 7200, $this->getOptions($filesystem->getOptions()));
        $this->assertArrayHasKey('easy-file/file-service.txt', $list);
        $this->assertArrayHasKey('easy-file/test.txt', $list);
    }

    public function testGetInternalLinks()
    {
        $filesystem = $this->getFilesystem();

        $options = $this->getOptions($filesystem->getOptions());
        $options['internal_endpoint'] = true;

        $list = $filesystem->getLinks([
            'easy-file/file-service.txt',
            'easy-file/test.txt',
        ], [], 7200, $options);
        $this->assertArrayHasKey('easy-file/file-service.txt', $list);
        $this->assertArrayHasKey('easy-file/test.txt', $list);
    }

    public function testGetLinksImage()
    {
        $filesystem = $this->getFilesystem();

        $options = [
            'image' => [
                [
                    'type' => 'resize',
                    'params' => [
                        'm' => 'lfit',
                        'l' => 100,
                        's' => 100,
                        'w' => 100,
                        'h' => 100,
                    ],
                ],
            ],
        ];
        $options = array_merge($options, $this->getOptions($filesystem->getOptions()));

        $list = $filesystem->getLinks([
            'easy-file/easy.jpeg',
        ], [], 7200, $options);
        $this->assertArrayHasKey('easy-file/easy.jpeg', $list);
    }

    public function testDestroy()
    {
        $filesystem = $this->getFilesystem();

        $filesystem->destroy([
            'easy-file/file-service.txt',
        ], $this->getOptions($filesystem->getOptions()));
        $this->assertTrue(true);
    }

    public function testDuplicate()
    {
        $filesystem = $this->getFilesystem();

        $path = $filesystem->duplicate('easy-file/test.txt', 'easy-file/test-copy.txt', $this->getOptions($filesystem->getOptions()));
        $this->assertIsString($path);
    }

    public function testAppendUpload()
    {
        $filesystem = $this->getFilesystem();

        // Use timestamp to ensure unique file name
        $testKey = 'easy-file/append-test-' . time() . '-' . uniqid() . '.txt';

        // Now perform append upload using non-STS credentials
        $credentialPolicy = new CredentialPolicy([
            'sts' => false,
        ]);

        $realPath = __DIR__ . '/../test.txt';
        $appendUploadFile = new AppendUploadFile($realPath, 0, $testKey);

        $filesystem->appendUploadByCredential($appendUploadFile, $credentialPolicy, $this->getOptions($filesystem->getOptions()));
        $this->assertTrue(true);
    }

    protected function getStorageName(): string
    {
        return 'file_service_test';
    }

    /**
     * Override base class method to support storage parameter for this test class.
     */
    protected function getFilesystem(?string $storage = null): FilesystemProxy
    {
        if ($storage === null) {
            // Call parent implementation when no parameter provided
            return parent::getFilesystem();
        }

        // Custom implementation with parameter support
        try {
            $easyFile = $this->createCloudFile();
            return $easyFile->get($storage);
        } catch (Exception $e) {
            $this->skipTestDueToMissingConfig($storage . ' configuration not available: ' . $e->getMessage());
        }
    }

    private function getOptions(array $options = []): array
    {
        return array_merge($options, [
            'cache' => false,
        ]);
    }
}
